﻿using Acme.ConcreteMixDesign.Dtos;
using Acme.ConcreteMixDesign.Players;
using Acme.ConcreteMixDesign.Top_Info;
using Acme.ConcreteMixDesign.TopicInformations;
using Acme.ConcreteMixDesign.Topics;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace Acme.ConcreteMixDesign
{
    public class TopicAppService : CrudAppService<Topic,TopicDto, Guid, PagedAndSortedResultRequestDto,CreateTopicDto,UpdateTopicDto>,ITopicAppService
    {
        private readonly ITopicRepository _topicRepository;
        private readonly IAnswerRepository _answerRepository;
        private readonly ITopicInformationRepository _informationRepository;
        private readonly ITopicAndInforRepository _topicAndInforRepository;
        private readonly IAnswerAppService _answerService;
        public TopicAppService( ITopicRepository topicRepository, IAnswerRepository answerRepository, ITopicInformationRepository informationRepository,ITopicAndInforRepository topicAndInforRepository,
            IAnswerAppService answerService) : base(topicRepository)
        {
            _topicRepository = topicRepository;
            _answerRepository = answerRepository;
            _informationRepository = informationRepository;
            _topicAndInforRepository = topicAndInforRepository;
            _answerService = answerService;
        }

        public override async Task<TopicDto> CreateAsync(CreateTopicDto input)
        {
            var newTopic = new Topic
            {
                TopicName = input.TopicName,
                TopicContent = input.TopicContent,
            };
           
            var newInfor = new List<TopicAndInfor>();
            var newTopic1 = await _topicRepository.InsertAsync(newTopic,true);
            foreach (var item in input.Answers)
            {
                item.TopicId = newTopic1.Id;
            }
            var answers = ObjectMapper.Map<List<CreateAnswerDto>, List<Answer>>(input.Answers);

            foreach (var answer in answers)
            {
                answer.TopicId = newTopic1.Id;
                answer.UpdateId();
            }
            await _answerRepository.InsertManyAsync(answers,true);
            
            foreach (var item in input.TopicInformations)
            {
                newInfor.Add(new TopicAndInfor
                {
                    Topid = newTopic1.Id,
                    InforId = item.Id
                });
            }
            await _topicAndInforRepository.InsertManyAsync(newInfor, true);
            
            var answersEntitys=await _answerRepository.GetListAsync(x=>x.TopicId.Equals(newTopic1.Id));
            var InforEntitys = new List<TopicInformation>();
            if (newInfor.Count > 0)
            {
                foreach (var item in newInfor)
                {
                    InforEntitys.Add(await _informationRepository.GetAsync(item.InforId));
                }
            }

            var newTopicDto = ObjectMapper.Map<Topic, TopicDto>(newTopic);
            newTopicDto.Answers = ObjectMapper.Map<List<Answer>, List<AnswerDto>>(answersEntitys);
            newTopicDto.TopicInformations = ObjectMapper.Map<List<TopicInformation>, List<TopicInformationDto>>(InforEntitys);
            return newTopicDto;
        }

        [HttpGet]
        [Route("GetAllTopic")]
        public async Task<List<TopicDto>> GetAllListAsync()
        {
            var i = await _topicRepository.GetListAsync();
            var o = ObjectMapper.Map<List<Topic>, List<TopicDto>> (i);
            List<Answer> aw = new List<Answer>();
            List<TopicAndInfor> ti = new List<TopicAndInfor>();
            List<TopicInformation> topicInformation = new List<TopicInformation>();
            
            foreach (var item in o)
            {
                aw = await _answerRepository.GetListAsync(a=>a.TopicId.Equals(item.Id));
                ti = await _topicAndInforRepository.GetListAsync(a => a.Topid.Equals(item.Id));
                if (ti.Count > 0)
                {
                    foreach(var d in ti)
                    {
                        topicInformation = await _informationRepository.GetListAsync(a => a.Id.Equals(d.InforId));
                    }
                }
                item.Answers = ObjectMapper.Map<List<Answer>, List<AnswerDto>>(aw);
            }
            return o;
        }

        public  override async Task<TopicDto> GetAsync(Guid id)
        {
            Topic i = await _topicRepository.FindAsync(a => a.Id == id);
            TopicDto enityDto = new TopicDto();
            if (i != null)
            {
                enityDto = ObjectMapper.Map<Topic, TopicDto>(i);
            }
            else
            {
                return await base.GetAsync(id);
            }
            List<Answer> aw = new List<Answer>();
            List<TopicAndInfor> ti = new List<TopicAndInfor>();
            List<TopicInformation> topicInformation = new List<TopicInformation>();
            aw = await _answerRepository.GetListAsync(a => a.TopicId.Equals(id));

            // 获取所有可能的 Type 的整数值
            var allTypes = Enum.GetValues(typeof(AnswerType)).Cast<int>().ToList();

            // 找到已有数据的 Type
            var existingTypes = aw.Select(a => (int)a.AnswerType).Distinct().ToList();

            // 找到缺失的 Type，并为其创建空的 Answer
            var missingTypes = allTypes.Except(existingTypes);
            foreach (var missingType in missingTypes)
            {
                aw.Add(new Answer { AnswerType = (AnswerType)missingType, /* 其他属性赋值，如果有的话 */ });
            }

            aw = aw.OrderBy(a => a.AnswerType).ToList();
            ti = await _topicAndInforRepository.GetListAsync(a => a.Topid.Equals(id));
            if (ti.Count > 0)
            {
                foreach (var d in ti)
                {
                    topicInformation.Add(await _informationRepository.GetAsync(a => a.Id.Equals(d.InforId)));
                }
            }
            enityDto.Answers = ObjectMapper.Map<List<Answer>, List<AnswerDto>>(aw);
            enityDto.TopicInformations = ObjectMapper.Map<List<TopicInformation>, List<TopicInformationDto>>(topicInformation);
            return enityDto;
        }

        public override async Task<TopicDto> UpdateAsync(Guid id, UpdateTopicDto input)
        {
            List<TopicAndInfor> topicAnds = new List<TopicAndInfor>();
            List<Answer> answers = new List<Answer>();
            List<TopicInformation> informations = new List<TopicInformation>();

            Topic updateTopic = await _topicRepository.GetAsync(id);
            foreach (var a in input.Answers)
            {
                if (a.Id != Guid.Empty)
                {
                    //必须增加true，不然会报409假修改
                    answers.Add(await _answerRepository.UpdateAsync(ObjectMapper.Map<AnswerDto, Answer>(a),true));
                }
                else
                {
                    var newAnw = ObjectMapper.Map<AnswerDto, Answer>(a);
                    newAnw.TopicId = id;
                    answers.Add(await _answerRepository.InsertAsync(newAnw,true));
                }
            }
            //在把中间表关于这道题的数据全部删掉再重新添加
            var oldInfoToTopic = await _topicAndInforRepository.GetListAsync(x=>x.Topid.Equals(id));
            if (oldInfoToTopic != null)
            {
                foreach (var a in oldInfoToTopic)
                {
                    await _topicAndInforRepository.DeleteAsync(a);
                }
            }
            if (input.TopicInformations.Count > 0)
            {
                foreach (var a in input.TopicInformations)
                {
                    var newInfo = new TopicAndInfor
                    {
                        Topid = id,
                        InforId = a.Id
                    };
                    topicAnds.Add(await _topicAndInforRepository.InsertAsync(newInfo, true));
                }
            }
            foreach (var a in topicAnds)
            {
                informations.Add(await _informationRepository.GetAsync(a.InforId));
            }
            updateTopic.TopicName = input.TopicName;
            updateTopic.TopicContent = input.TopicContent;
            var i = await _topicRepository.UpdateAsync(updateTopic,true);
            var newTopic = ObjectMapper.Map<Topic, TopicDto>(updateTopic);



            newTopic.Answers = ObjectMapper.Map<List<Answer>, List<AnswerDto>>(answers);
            newTopic.TopicInformations = ObjectMapper.Map<List<TopicInformation>, List<TopicInformationDto>>(informations);
            return newTopic;
        }
    }
}
